package com.whc.common;

import com.whc.common.design.handle.type.*;
import com.whc.common.design.key.KeyGenerate;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * @author wang-hai-cheng
 * @since 2021/12/29 21:03
 */
@Component
public class Context implements ApplicationContextAware {
    public static Map<String, KeyGenerate> keys = new Hashtable<>();
    public static Map<String, Class<?>> autoColumn = new HashMap<>();
    public static TypeChain typeHandle = new SaveChain();
    /**
     * 上下文对象实例
     */
    private static ApplicationContext applicationContext;

    static {
        autoColumn.put("id", Long.class);
        autoColumn.put("create_time", LocalDateTime.class);
        autoColumn.put("create_user_id", Long.class);
        autoColumn.put("update_time", LocalDateTime.class);
        autoColumn.put("update_user_id", Long.class);
    }

    public static Object keyGenerate(Class<? extends KeyGenerate> clazz) {
        KeyGenerate generate;
        KeyGenerate o = keys.get(clazz.getName());
        if ((generate = o) == null) {
            try {
                generate = clazz.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return "";
            }
            keys.put(clazz.getName(), generate);
        }
        return generate.generate();
    }

    @PostConstruct
    public void aaa() {
        typeHandle
                .addHandle(new UpdateChain())
                .addHandle(new SaveOrUpdateChain())
                .addHandle(new DeleteChain())
                .addHandle(new DetailChain())
                .addHandle(new ListChain())
                .addHandle(new PageChain())

                .addHandle(new EndChain());//此调用链必须放在最下面
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Context.applicationContext = applicationContext;
    }

    /**
     * 获取Spring上下文
     *
     * @return spring上下文
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取Bean
     *
     * @param name bean的名字
     * @return bean对象
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通过class获取Bean
     *
     * @param clazz 获取的bean类型
     * @return bean对象
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通过name,以及Clazz返回指定的Bean
     *
     * @param name  获取的bean名
     * @param clazz 获取的bean类型
     * @return bean对象
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}